﻿using ChongJu.EventManager;
using ChongJu.EventManager.Rating;
using ChongJu.ModelManager.MQTT;
using ChongJu.ModelManager.Rating;
using MQTTnet;
using MQTTnet.Client;
using MQTTnet.Client.Connecting;
using MQTTnet.Client.Options;
using Public.Logger;
using Public.Tools;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Threading.Tasks;

namespace ChongJu.MQTT
{
    public class MQTTService
    {
        private static readonly object _obj = new object();
        private static MQTTService _instance;
        public static MQTTService Instance
        {
            get
            {
                if (_instance == null)
                    lock (_obj)
                        if (_instance == null)
                            _instance = new MQTTService();

                return _instance;
            }
        }

        private MqttClient _client;
        private IMqttClientOptions _options;

        public bool Connected { get; private set; }

        public bool Init(string id)
        {
            try
            {
                Connected = false;
                if (int.TryParse(Tool.GetConfig("MqttPort"), out var port) == false)
                    return false;

                var factory = new MqttFactory();
                _client = factory.CreateMqttClient() as MqttClient;
                _options = new MqttClientOptionsBuilder()
                              .WithTcpServer(Tool.GetConfig("MqttIP"), port)
                              .WithCredentials(Tool.GetConfig("MqttUserName"), Tool.GetConfig("MqttPassword"))
                              .WithClientId(Tool.GuidTo16String())
                              .Build();

                _client.ConnectAsync(_options);

                _client.UseConnectedHandler(async e =>
                {
                    var topicFilterBuilder = new MqttTopicFilterBuilder()
                                             .WithTopic("public")
                                             .Build();
                    await _client.SubscribeAsync(topicFilterBuilder);

                    topicFilterBuilder = new MqttTopicFilterBuilder()
                                             .WithTopic(id)
                                             .Build();
                    await _client.SubscribeAsync(topicFilterBuilder);

                    Connected = true;
                    InitModel.MQ = true;
                    ConnectStatusEvent.OnConnect(ConnectType.MQTT, true);
                });

                _client.UseDisconnectedHandler(e =>
                {
                    Connected = false;
                    MQTTReconnecting();
                    InitModel.MQ = false;
                    ConnectStatusEvent.OnConnect(ConnectType.MQTT, false);
                });

                _client.UseApplicationMessageReceivedHandler(e =>
                {
                    var msg = Encoding.UTF8.GetString(e.ApplicationMessage.Payload);
                    var res = Tool.JsonToObject<MqttCommandModel>(msg);

                    CommonEvent.OnSystemCommand(res);
                    Logger.Warn($"接收到指令：{msg}");
                });
                return true;
            }
            catch (Exception ex)
            {
                Logger.Error("初始化MQTT异常", ex);
                return false;
            }
        }

        private async void MQTTReconnecting()
        {
            try
            {
                await _client.ConnectAsync(_options);
                await Task.Delay(1000 * 3);
                Logger.Debug("重连MQTT");
            }
            catch(Exception ex)
            {
                Connected = false;
                //donothing
            }
        }
    }
}
